const fs = require('fs');
const path = require('path');
const https = require('https');
const puppeteer = require('puppeteer');
const { start } = require('repl');

(async () => {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();

    // 配置浏览器参数
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
    await page.setViewport({ width: 1280, height: 800 });

    // 跳转到指定文章
    await page.goto('https://www.miyoushe.com/ys/article/62978099', {
        waitUntil: 'networkidle2',
        timeout: 60000
    });

    // 等待并点击表情入口按钮
    const biaoqing = await page.waitForSelector('.mhy-icon.iconfont.icon-biaoqing', { visible: true });
    await biaoqing.scrollIntoView();
    await page.evaluate(() => {
        document.querySelector('.mhy-icon.iconfont.icon-biaoqing').click();
    });

    // 等待表情面板加载完成
    await page.waitForSelector('.mhy-emoticon__list', {
        visible: true,
        timeout: 10000
    });

    // 表情包目标页号和位置序号
    const targetPage = 2, targetNum = 4;
    // 表情包下载路径
    const downloadDir = "C:/Users/xiaoan/Pictures/表情包/原神官方表情包";

    // 翻到指定表情包页
    let currentPage = 1;
    while (currentPage != targetPage) {
        const nextButton = await page.$('.mhy-emoticon__next:not(.mhy-emoticon__pagerbtn--disabled)');
        if (!nextButton) {
            // 按钮不可用，无法翻页
            console.error(`错误! 共查询到${currentPage}页，但目标为第${targetPage}页`);
            return;
        } else {
            // 翻下一页
            await nextButton.click();
            currentPage++;
        }
    }

    // 获取当前页所有表情包类型按钮
    const typeButtons = await page.$$('.mhy-emoticon__setlist > .mhy-emoticon__set');
    if (typeButtons.length < targetNum) {
        console.error(`当前${currentPage}页无第${targetNum}'个表情包按钮`);
        return;
    }

    // 点击该组表情包按钮
    await typeButtons[targetNum - 1].click();
    // 获取表情包列表
    const emoticons = await getCurrentPageEmoticons(page);
    // 处理该类型的表情包列表
    await processEmoticons(emoticons, downloadDir);
    await browser.close();
})();


// 获取当前页的表情包
async function getCurrentPageEmoticons(page) {
    return page.$$eval('.mhy-emoticon__list .mhy-emoticon__item', elements =>
        elements.map(el => ({
            title: el.title,
            url: el.style.backgroundImage.match(/url\(["']?(.*?)["']?\)/)[1]
        }))
    );
}

// 下载表情包并保存到本地
async function processEmoticons(emoticons, downloadDir) {

    // 跳过计数、新增计数、失败计数
    let stepCount = 0, newCount = 0, errCount = 0;
    for (let index = 0; index < emoticons.length; index++) {
        const emoticon = emoticons[index];
        // 日志打印进度，清除当前行，光标回到0位置
        process.stdout.clearLine();
        process.stdout.cursorTo(0);
        process.stdout.write(`[-----${index + 1}/${emoticons.length}-----]`);
        try {
            // 构建下载路径
            const { fileDir, fileName } = parseToPath(emoticon.title);
            const finalDir = fileDir ? path.join(downloadDir, fileDir) : downloadDir;
            const filePath = path.join(finalDir, `${fileName}.png`);
            // 检查文件是否存在
            if (fs.existsSync(filePath)) {
                process.stdout.write(`[跳过] 已存在: ${filePath} \r`);
                stepCount++;
                continue;
            }

            // 创建目录
            if (!fs.existsSync(finalDir)) {
                fs.mkdirSync(finalDir, { recursive: true });
            }

            // 下载文件
            await downloadImage(emoticon.url, filePath);
            newCount++;
            process.stdout.write(`[成功] 下载: ${filePath} \r`);

            // 下载成功后增加随机延迟
            await delay(500, 1000); // 随机延迟0.5-1秒

        } catch (err) {
            errCount++;
            process.stdout.write(`[失败] 处理表情 "${emoticon.title}" \r`);
        }
    }
    console.log(`\n下载完毕,统计如下:\n-跳过下载${stepCount}张表情包\n-新增下载${newCount}张表情包\n-下载失败${errCount}张表情包`);
}

// 解析标题，获取子目录和文件名
function parseToPath(inputStr, options = {}) {
    // 配置参数
    const {
        separators = /[\s_,=-]+/, // 支持的分隔符（可扩展）
        maxDepth = 10,            // 最大目录层级
        cleanPolicy = {           // 清理规则
            removeIllegal: true,
            trimSpace: true,
            maxLength: 50,
            lowercase: false
        },
        defaultName = ''   // 默认名称
    } = options;

    // 阶段1：字符串预处理
    let parts = inputStr
        // 拆分字符串
        .split(separators)
        // 过滤空值及无效内容
        .filter(p => {
            const str = p.trim();
            return str.length > 0 && str !== '.';
        });

    // 阶段2：内容清洗
    const cleaned = parts.map(part => {
        let str = part;

        // 应用清理策略
        if (cleanPolicy.trimSpace) str = str.trim();
        if (cleanPolicy.removeIllegal) {
            str = str.replace(/[<>:"/\\|?*]/g, '');
        }
        if (cleanPolicy.maxLength) {
            str = str.substring(0, cleanPolicy.maxLength);
        }
        if (cleanPolicy.lowercase) {
            str = str.toLowerCase();
        }

        return str;
    })
        // 二次过滤空值
        .filter(p => p.length > 0);

    // 阶段3：路径生成
    if (cleaned.length === 0) {
        return {
            fileDir: '',
            fileName: defaultName
        };
    }

    // 阶段3：拆分目录和文件名
    const lastIndex = cleaned.length - 1;
    const dirComponents = cleaned.slice(0, lastIndex);
    let fileName = cleaned[lastIndex];

    return {
        fileDir: path.join(...dirComponents),
        fileName: fileName || defaultName
    };
}

// 下载图片
async function downloadImage(url, filePath) {
    return new Promise((resolve, reject) => {
        https.get(url, response => {
            if (response.statusCode !== 200) {
                return reject(new Error(`HTTP ${response.statusCode}`));
            }

            const fileStream = fs.createWriteStream(filePath);
            response.pipe(fileStream);

            fileStream.on('finish', () => {
                fileStream.close();
                resolve();
            });
        }).on('error', err => {
            reject(err);
        });
    });
}

// 随机延迟
const delay = (min = 1000, max = 3000) => {
    const duration = Math.random() * (max - min) + min;
    return new Promise(resolve => setTimeout(resolve, duration));
};

// 用户中断脚本
process.on('SIGINT', () => {
    console.log('\n脚本已被用户中断');
    process.exit(0);
});